package de.hu.wbi.histoner.eval;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

/**
Copyright 2011,2012 Philippe Thomas
This file is part of histoner.

HistoNer is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
any later version.

HistoNer  is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with HistoNer .  If not, see <http://www.gnu.org/licenses/>.
*/

/**
 * Compare predictions of HistoNer against the manually annotated gold standard
 * @author philippe
 * @version 1.0
 */
public class Evaluate {
		
	private static String predictFile; 	//File containing the predictions 
	private static String goldFile; 	//File containing gold standard annotations
	
	public static void main(String[] args) throws IOException{
		parseArgs(args);
		
		HashMap<Integer, ArrayList<String>> predict = readPredict(predictFile);
		HashMap<Integer, ArrayList<String>> gold = readPredict(goldFile);
		
		int tp=0; int fp=0; int fn=0;
		for(int pmid:gold.keySet()){		//Iterate over all articles in the gold-standard
			
			if(!predict.containsKey(pmid)){	//If we actually predicted no modification; all of them are false negatives
				fn+= gold.get(pmid).size();
				continue;
			}
			
			ArrayList<String> predictMods = predict.get(pmid);
			ArrayList<String> goldMods = gold.get(pmid);			
			
			for(String s:predictMods){
				
				if(goldMods.size() == 0 || !goldMods.contains(s)){
					fp++;
//					System.out.println("FP\t" +pmid +"\t" +s);
				}					
				else{
					tp++;
					goldMods.remove(s);
				}					
			}

			//All remaining modifications must be false negatives
			fn+=goldMods.size();
			for(String s:goldMods){
//				System.out.println("FN\t" +pmid +"\t" +s);
			}
		}
		
		System.out.println("TP " +tp);
		System.out.println("FP " +fp);
		System.out.println("FN " +fn);
		double prec= (double)tp/(tp+fp);
		double recall= (double)tp/(tp+fn);
		double f1  = 2*prec*recall/(prec+recall);
			
		System.out.println("P= " +String.format("%.3g", prec) +"; R=" +String.format("%.3g", recall) +"; F1=" +String.format("%.3g", f1));
	}
	
	/**
	 * Parse the command line parameters
	 * @param args Arguments from main method
	 */
	private static void parseArgs(String [] args){
		if(args.length != 4 ){
			printUsage();
			System.exit(1);
		}
			
		for(int i=0; i<args.length; i+=2){
			if(args[i].equals("-p") || args[i].equals("--prediction"))
				predictFile = args[i+1];
			
			else if(args[i].equals("-g") || args[i].equals("--gold"))
				goldFile = args[i+1];
			
			else{
				System.err.println("Unknown option " +args[i]);
				System.exit(1);
			}
		}	
		
		System.err.println("Starting evaluation");
		System.err.println("Prediction file " +predictFile);
		System.err.println("Goldstandard file " +goldFile);
	}
	
	/**
	 * Prints a simple usage information
	 */
	private static void printUsage() {
        System.err.println(
        		"Evaluates the quality of named entity Recognition" +
        		"Usage:\n" +
        		"Prediction file [-p, --prediction]\n" +
        		"Goldstandard file [-g, --gold]\n"
        		);
	}

	/**
	 * Reads annotations produced by manual annotation or by named entity recognition
	 * @param fileName File to be loaded
	 * @return HashMap, being pmid-id the key and a List of histone modifications found/annotated for this corpus 
	 * @throws IOException is thrown if an exception during file handling occurs
	 */
	private static HashMap<Integer, ArrayList<String>> readPredict(String fileName) throws IOException{
		HashMap<Integer, ArrayList<String>> result = new  HashMap<Integer, ArrayList<String>>();
		
		BufferedReader br = new BufferedReader(new FileReader(fileName));
		String line;
		while((line=br.readLine()) != null){
			
			if(line.startsWith("#"))	//Skip comment lines
				continue;
			
			String array[] = line.split("\t");
			int pmid  = Integer.parseInt(array[0]);
			
			if(array.length == 5){
				ArrayList<String> tmp = new ArrayList<String>();
				tmp.add(array[4]);				
				if(result.containsKey(pmid))
					tmp.addAll(result.get(pmid));
				result.put(pmid, tmp);
			}
			
			else{
				ArrayList<String> tmp = new ArrayList<String>();
				for(int i =4; i<array.length; i++){
					tmp.add(array[i]);					
				}
				
				if(result.containsKey(pmid))
					tmp.addAll(result.get(pmid));
				result.put(pmid, tmp);
			}
		}
		br.close();
		return result;
	}
	

}
